28. Implement Quintic Polynomial Solver Solution

Quintic Polynomial Solver Solution

Below is one potential solution for the quintic polynomial solver.

Start Quiz:

#include <cmath>
#include <iostream>
#include <vector>

#include "Dense"
#include "grader.h"

using std::vector;
using Eigen::MatrixXd;
using Eigen::VectorXd;

/**
 * TODO: complete this function
 */
vector<double> JMT(vector<double> &start, vector<double> &end, double T) {
  /**
   * Calculate the Jerk Minimizing Trajectory that connects the initial state
   * to the final state in time T.
   *
   * @param start - the vehicles start location given as a length three array
   *   corresponding to initial values of [s, s_dot, s_double_dot]
   * @param end - the desired end state for vehicle. Like "start" this is a
   *   length three array.
   * @param T - The duration, in seconds, over which this maneuver should occur.
   *
   * @output an array of length 6, each value corresponding to a coefficent in 
   *   the polynomial:
   *   s(t) = a_0 + a_1 * t + a_2 * t**2 + a_3 * t**3 + a_4 * t**4 + a_5 * t**5
   *
   * EXAMPLE
   *   > JMT([0, 10, 0], [10, 10, 0], 1)
   *     [0.0, 10.0, 0.0, 0.0, 0.0, 0.0]
   */
  MatrixXd A = MatrixXd(3, 3);
  A << T*T*T, T*T*T*T, T*T*T*T*T,
       3*T*T, 4*T*T*T,5*T*T*T*T,
       6*T, 12*T*T, 20*T*T*T;
    
  MatrixXd B = MatrixXd(3,1);     
  B << end[0]-(start[0]+start[1]*T+.5*start[2]*T*T),
       end[1]-(start[1]+start[2]*T),
       end[2]-start[2];
          
  MatrixXd Ai = A.inverse();
  
  MatrixXd C = Ai*B;
  
  vector <double> result = {start[0], start[1], .5*start[2]};

  for(int i = 0; i < C.size(); ++i) {
    result.push_back(C.data()[i]);
  }

  return result;
}

int main() {

  // create test cases
  vector< test_case > tc = create_tests();

  bool total_correct = true;

  for(int i = 0; i < tc.size(); ++i) {
    vector<double> jmt = JMT(tc[i].start, tc[i].end, tc[i].T);
    bool correct = close_enough(jmt, answers[i]);
    total_correct &= correct;
  }

  if(!total_correct) {
    std::cout << "Try again!" << std::endl;
  } else {
    std::cout << "Nice work!" << std::endl;
  }

  return 0;
}
#ifndef GRADER_H
#define GRADER_H

#include <cmath>
#include <vector>

using std::vector;

struct test_case {
    vector<double> start;
    vector<double> end;
    double T;
};

bool close_enough(vector<double> &poly, vector<double> &target_poly, 
                  double eps=0.01) {
  if (poly.size() != target_poly.size()) {
    std::cout << "Your solution didn't have the correct number of terms" 
              << std::endl;
    return false;
  }

  for (int i = 0; i < poly.size(); ++i) {
    double diff = poly[i]-target_poly[i];
    if (abs(diff) > eps) {
      std::cout << "At least one of your terms differed from target by more than " 
                << eps << std::endl;
      return false;
    }
  }

  return true;
}

vector<test_case> create_tests() {
  // Create test case vector
  vector<test_case> tc;

  test_case tc1;
  tc1.start = {0,10,0};
  tc1.end = {10,10,0};
  tc1.T = 1;
  tc.push_back(tc1);

  test_case tc2;
  tc2.start = {0,10,0};
  tc2.end = {20,15,20};
  tc2.T = 2;
  tc.push_back(tc2);

  test_case tc3;
  tc3.start = {5,10,2};
  tc3.end = {-30,-20,-4};
  tc3.T = 5;
  tc.push_back(tc3);
  
  return tc;
}

vector<vector<double>> answers = {{0.0, 10.0, 0.0, 0.0, 0.0, 0.0},
                                  {0.0,10.0,0.0,0.0,-0.625,0.3125},
                                  {5.0,10.0,1.0,-3.0,0.64,-0.0432}};

#endif  // GRADER_H